package com.ada.config;

import com.ada.annoations.Delete;
import com.ada.annoations.Insert;
import com.ada.annoations.Select;
import com.ada.annoations.Update;
import com.ada.pojo.Configuration;
import com.ada.pojo.MappedStatement;
import com.ada.sqlSession.OperationType;
import org.dom4j.DocumentException;

import java.io.InputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;

public class AnnotationMapperBuilder {
    private Configuration configuration;
    private final Set<Class<? extends Annotation>> sqlAnnotationTypes = new HashSet<Class<? extends Annotation>>();
    public AnnotationMapperBuilder(Configuration configuration) {
        this.configuration = configuration;
        sqlAnnotationTypes.add(Select.class);
        sqlAnnotationTypes.add(Insert.class);
        sqlAnnotationTypes.add(Update.class);
        sqlAnnotationTypes.add(Delete.class);
    }

    public void parse(Class<?> mapperClass) throws DocumentException {
        String namespace = mapperClass.getName();
        for (Method method : mapperClass.getMethods()) {
            try {
                MappedStatement mappedStatement = new MappedStatement();
                mappedStatement.setId(method.getName());
                Type type=method.getGenericReturnType();
                if (type instanceof ParameterizedType) {//获取对应的返回类型
                    ParameterizedType parameterizedType=(ParameterizedType)type;
                    mappedStatement.setResultType(parameterizedType.getActualTypeArguments()[0].getTypeName());
                }else {
                    mappedStatement.setResultType(method.getReturnType().getName());
                }
                if(method.getParameterTypes().length!=0){
                    mappedStatement.setParamterType(method.getParameterTypes()[0].getName());//这里暂时只取一个参数
                }
                Class<? extends Annotation> annotionClass=getSqlAnnotationType(method);
                Annotation sqlAnnotation = method.getAnnotation(annotionClass);
                final String[] strings = (String[]) sqlAnnotation.getClass().getMethod("value").invoke(sqlAnnotation);
                mappedStatement.setSql(strings[0]);//获取sql语句
                OperationType operationType = OperationType.valueOf(annotionClass.getSimpleName().toUpperCase(Locale.ENGLISH));
                mappedStatement.setOperationType(operationType);//通过注解名得到操作类型
                String key = namespace + "." + method.getName();//sql的唯一标识:namespace.id
                configuration.getMappedStatementMap().put(key,mappedStatement);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    //获取方法对应的注解类型
    private Class<? extends Annotation> getSqlAnnotationType(Method method) {
        for (Class<? extends Annotation> type : sqlAnnotationTypes) {
            Annotation annotation = method.getAnnotation(type);
            if (annotation != null) {
                return type;
            }
        }
        return null;
    }
}
